home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / std / c++ / 527 < prev    next >
Encoding:
Internet Message Format  |  1996-08-06  |  12.3 KB

  1. Path: chronicle.mti.sgi.com!austern
  2. From: kanze@gabi.gabi-soft.fr (J. Kanze)
  3. Newsgroups: comp.std.c++
  4. Subject: Re: class.union questions
  5. Date: 16 Feb 1996 09:15:48 PST
  6. Organization: GABI Software, Sarl.
  7. Approved: austern@isolde.mti.sgi.com
  8. Message-ID: <KANZE.96Feb16160724@gabi.gabi-soft.fr>
  9. References: <v01530501ad3e247b1270@[194.163.74.11]>
  10. NNTP-Posting-Host: isolde.mti.sgi.com
  11. X-Original-Date: 16 Feb 1996 15:07:24 GMT
  12. In-Reply-To: dirk@becker.adviser.com's message of 10 Feb 1996 15:39:23 GMT
  13. X-Auth: PGPMoose V1.1 PGP comp.std.c++
  14.     iQBVAwUBMSS73Ey4NqrwXLNJAQHyvQH9EyHNtQwm2URxZyG+53xFtvs2Z1JndlUf
  15.     mh/Ox+y6n5o/JfsVr4I/5yZvrwdP8iFBp9bmuWCdpVvbq/OtDjwXfA==
  16.     =5HFd
  17. Originator: austern@isolde.mti.sgi.com
  18.  
  19. In article <v01530501ad3e247b1270@[194.163.74.11]>
  20. dirk@becker.adviser.com (Dirk Becker) writes:
  21.  
  22. > The first replies to my (DB) original posting seem to have the same
  23. > objection against my interpretation of b). This is my major problem,
  24. > so I put it first now.
  25. > James Kanze (JK) and John Max Skaller (JS) wrote:
  26. > From the WP: [class.union]
  27. > b) "An object of a class with a non-trivial default constructor
  28. >      (_class.ctor_), a non-trivial copy constructor (_class.copy_),
  29. >      a non-trivial destructor (_class.dtor_), or a non-trivial copy
  30. >      assignment operator (_over.ass_, _class.copy_) cannot be a member
  31. >      of a union,"
  32. > DB> This is a major reduction of the restrictions found in ARM, where all
  33. > DB> kinds of constructors or assignment operators were excluded. Here is
  34. > DB> also a note to give the explanation by the assumption, any member
  35. > DB> functions and especially assignments would usually expect a correctly
  36. > DB> constructed object.
  37. > JS>       No. It is merely a more precise statement of the same
  38. > JS> restrictions using more technical terminology.
  39. > JK> This is, in fact, exactly the restriction in the ARM.  All that has
  40. > JK> changes is the way things are described.  In the ARM, classes may or
  41. > JK> may not have constructors (destructors, assignment operators). In the
  42. > JK> current standard, *EVERY* class/struct has a copy constructor, an
  43. > JK> assignment operator and a destructor; the distinction is that some of
  44. > JK> these are trivial.
  45. > I still disagree totally. Please tell me what I'm reading wrong.
  46. > The ARM (mine is an early edition, 1990) does a complete restriction
  47. > against *any* constructor, destructor or user-defined assignment for
  48. > union member objects. (Section 9.5, page 182). The only explanation for
  49. > this rule was already summarized in my original posting, quoted above;
  50. > it has nothing to do with bitwise copy.
  51. > The WP indeed allows member objects with a rich set of constructors
  52. > and assignment operators. It does only <g> cripple the 4 most commonly
  53. > used special member functions, exactly naming them, into trivialness.
  54. > - default constructor
  55. > - destructor
  56. > - copy constructor
  57. > - copy assignment
  58. > I assume this exact enumeration implies all other variants of constructor
  59. > and assignment in member objects are free for user defined versions.
  60.  
  61. I'm not really sure what the restriction on constructors is meant to
  62. signify.  If the member has a constructor, then the compiler cannot
  63. generate a default constructor for it.  IMHO, this should imply that it
  64. cannot be a member, i.e.: that the words should be that member objects
  65. must have trivial default constructors, and not that they cannot have
  66. non-trivial default constructors.
  67.  
  68. The problem is how to construct the union.  If the union has no user
  69. provided constructor, then it cannot be constructed, because the
  70. compiler cannot generate a default constructor for it.  But if the union
  71. has a user defined constructor?  Does the user defined constructor have
  72. to initialize the member (presumably yes)?  And what if there are two
  73. such members?  Does the user defined constructor have to initialize both
  74. of them (bad news either way)?
  75.  
  76. I'll admit to not having thought about the other possible assignment
  77. operators.  Since other assignment operators do not inhibit the
  78. generation of the copy assignment operator, though, the additional
  79. freedom poses no problem.
  80.  
  81.     [...]
  82. > a)  "A union shall not have base classes. A union shall not be used as
  83. >       a base class."
  84. > JK> Without this rule, you either break the address rule, or you impose
  85. > JK> some special class layout on unions.
  86. > The union has no special class layout? I would say it is very special.
  87. > "a class whose member objects all begin at offset zero"
  88.  
  89. Poor wording on my part.  This is the address rule that must be
  90. maintained.
  91.  
  92. > /* my sample of union inheritance */
  93. > JK> This is generally handled better by an abstract base class and
  94. > JK> virtual functions.
  95. > Sure, I like polymorphic objects. But if you have a vast amount of
  96. > really small objects you may get tempted to use the reduced footprint
  97. > of a (1 or 2 byte) tag instead of a sizeof(ptr) vptr.
  98. > It is also slightly faster to load these unions from a binary file
  99. > than from a stream, allocate, dispatch and construct every single
  100. > object and retrieve every single member.
  101.  
  102. In practice, alignment restrictions are likely to mean that you loose at
  103. least the size of a pointer even if you declare the tag as a byte.
  104.  
  105. They advantage of using an integral constant tag is non-negligible when
  106. writing to a file, but since in practice, you cannot simply write a
  107. binary image to a file directly anyway, I don't see this as a great
  108. problem.
  109.  
  110. > /* union with longlong as member */
  111. > DB> If you are lucky to have some native long long datatype, then this
  112. > DB> would be legal code. If you already had to implement your own
  113. > DB> class longlong, now you lost the chance to use it (here).
  114. > JK> This is a problem, but... how would the compiler know when to call
  115. > JK> the constructor/destructor of your longlong?
  116. > Sorry for the wrong sample, longlong may work with trivial c/dtor and
  117. > copy operations. The same is with some class Complex.
  118. > Let's reconsider a class "string" and reference-counter features as
  119. > sideeffects. The answer for your question - how would the compiler
  120. > know? - came with my conclusion as quoted below: Just tell him.
  121. > Here the union constructor itself gets responsible for construction as
  122. > the correct union variant - e.g. choose the correct discriminator tag,
  123. > like "empty".
  124.  
  125. The problem is that unions (C and C++ unions, at least), don't have
  126. discriminator tags.  If you add one, it is no longer a union.
  127.  
  128. > DB> I would generally prefer " ... constructors and destructor of member
  129. > DB> objects are ignored, if not explicitly called by the union's ctor/dtor.
  130. > DB> The union's implicit default copy constructor / assignment does a
  131. > DB> binary copy instead of memberwise copy. Objects <containing a vptr>
  132. > DB> cannot be member of a union" - Please pardon my shortcut on vptrs.
  133. > The missing sample for this:
  134. > class Member {
  135. > public:
  136. >   Member();
  137. >   // ...
  138. > };
  139. > class Other {
  140. > public:
  141. >   Other();
  142. >   // ...
  143. > };
  144. > union Union {
  145. >   Union();
  146. >   Union(int);
  147. >   // ...
  148. >   Member m;
  149. >   Other  o;
  150. > };
  151. > Union::Union()
  152. > { // call none of the base member constructors
  153. > }
  154. > // call Member::Member() using a wellknown notation
  155. > Union::Union(int a)
  156. > : m()
  157. > { }
  158. > // deluxe variant - but this would mean a severe extension
  159. > Union::Union(int tag)
  160. > : tag==1 ? m()  // call Member::Member()
  161. > : tag==2 ? o()  // otherwise call Other::Other()
  162. > { }
  163.  
  164. The extension was discussed, but not adapted.  Ask the Australian
  165. delegation about discriminated unions.
  166.  
  167. > c) "A union can be thought of as a class"
  168. > DB> Here you accept the implications of 12.8.8 and 12.8.13 on implicitly
  169. > DB> defined copy constructor and copy assignment. The already trivial
  170. > DB> copy constructor/assignment of the member objects will then result
  171. > DB> in one large repetition of copies from and to the same memory locations.
  172. > DB> To avoid this behaviour I would strongly recommend to implement your
  173. > DB> own copy constructor or assignment whenever you use a union, because a
  174. > DB> memberwise copy is usually not desired.
  175. > JK> Basically, if you study the restrictions on unions carefully, the
  176. > JK> rules are such that a bitwise copy *must* be legal for assignment and
  177. > JK> copy construction.  This is the only type of copy the compiler can
  178. > JK> cope with in the absense of a discriminator to tell it which element
  179. > JK> of the union is valid.
  180. > JK> IMHO: if you feel that your union needs a copy constructor or an
  181. > JK> assignment operator, you are probably doing something wrong, in the
  182. > JK> sense that you are trying to use unions in a way that they are not
  183. > JK> intended.  (As they are defined in the standard. If they were defined
  184. > JK> differently, they might have different reasonable uses.)
  185. > I knew, but some compiler implementors forget their homework here.
  186. > If for any reason (generated source) you have a union with lots of
  187. > members, you may accidentally get lots of redundant code. This is
  188. > another reason for implicit bitwise copy.
  189. > And if the trivialness requirement were removed from the copy
  190. > operations, like in my (very draft) replacement text quoted above,
  191. > you would also loose the equivalence.
  192. > From a discussion outside this newsgroup I finally got a hint on the
  193. > intention behind the new restrictions: They should ensure a bitwise
  194. > copy of the union will copy the current union member correctly.
  195. > This is achieved by forcing bitwise copy for any potential member.
  196. > Why did you then not stay just with the POD union? With the
  197. > differentiation between POD union and non-POD union you already
  198. > got the higher degree of complexity, only to undo this with lots
  199. > of additional words.
  200.  
  201. My position was that a union is not a class; it is an entirely different
  202. type of object, which just happens to have some class-like features.
  203. The position actually adapted, however, is that a union is a class, with
  204. a lot of restrictions.  (It wasn't adapted because there were
  205. alternative proposals that were voted on.  It was adapted because there
  206. was no proposal, and this was the closest to what was in the base
  207. documents, the ARM and the C standard.)
  208.  
  209. > My first incident with this problem went what I would call a
  210. > user's way instead of the implementor's sight: How can we use
  211. > it? Instead of "How to infer the implicit implementation?"
  212. > Here I felt invited by the WP to use most of the member object
  213. > assignments and than fell into the trivialness trap.
  214. > If your intention is bitwise copy as implicit copy for the union
  215. > itself, why not just call it by its real name instead of hiding
  216. > behind "trivialness"?
  217.  
  218. Because the standard does not define the idea of bitwise copy; it does
  219. define `trivial' (for constructors, destructors, etc.).  The business
  220. concerning bitwise copy really belongs in a rationale.
  221.  
  222. > "The implicit union copy constructor and copy assignment apply
  223. > bitwise copy."
  224. > No trivialness restrictions on the member objects!
  225.  
  226. But you then need something to specify what types of objects can be
  227. safely copied with bitwise copy.  This is simply begging the point.
  228.  
  229. There was some discussion about allowing anything in a union, but using
  230. bitwise copy anyway.  This was felt to be far too dangerous.
  231.  
  232. > If someone then decides to have member objects with other copy
  233. > constructor or assignment semantics, he/she just has to provide
  234. > own union copy operations.
  235. > -----
  236. > Some new questions:
  237. > e) "At most one of the member objects can be stored in a union at
  238. >     any time."
  239. > Has anybody already thought about the memberwise implicit operations in
  240. > regard to this rule?
  241. > OK, we'll meet again at the bitwise copy, but this is at least nowhere
  242. > explicitly mentioned in the WP.
  243. > -----
  244. > f)
  245. > Why is [class.mem] 15 restricted to POD structs as union members?
  246. > vptrs are already excluded for union members, and I would still
  247. > ask to exclude them when dropping the trivialness.
  248.  
  249. References, I suppose.  They also cause problems with bitwise copy.  Of
  250. course, a class or a struct with a reference must have a user defined
  251. constructor, so it presumably cannot be a member of a union (see above).
  252. -- 
  253. James Kanze           (+33) 88 14 49 00          email: kanze@gabi-soft.fr
  254. GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
  255. Conseils, itudes et rialisations en logiciel orienti objet --
  256.               -- A la recherche d'une activiti dans une region francophone
  257. ---
  258. [ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  259.   Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy is
  260.   in http://reality.sgi.com/employees/austern_mti/std-c++/policy.html. ]
  261.